package com.jzo2o.orders.manager.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.api.orders.dto.request.OrderCancelReqDTO;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.TradingApi;
import com.jzo2o.api.trade.dto.request.PayReqDTO;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.dto.response.PayResDTO;
import com.jzo2o.api.trade.enums.PayChannelEnum;
import com.jzo2o.api.trade.enums.PayTypeEnum;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.mvc.utils.UserContext;
import com.jzo2o.orders.base.enums.OrderPayStatusEnum;
import com.jzo2o.orders.base.enums.OrderStatusEnum;
import com.jzo2o.orders.base.mapper.OrdersMapper;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.manager.hander.*;
import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO;
import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO;
import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO;
import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO;
import com.jzo2o.orders.manager.service.IOrdersCanceledService;
import com.jzo2o.orders.manager.service.IOrdersCreateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 下单服务类
 * </p>
 *
 * @author itcast
 * @since 2023-07-10
 */
@Slf4j
@Service
public class OrdersCreateServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersCreateService {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private IOrdersCanceledService ordersCanceledService;

    @Resource
    private TradingApi tradingApi;

    @Resource
    private RefundRecordApi refundRecordApi;

    @Override
    public PlaceOrderResDTO placeOrder(PlaceOrderReqDTO placeOrderReqDTO) {

        //防止重复下单
        // 1. 唯一索引
        //2 分布式锁
        String key = "order_place:" + placeOrderReqDTO.getServeId() + UserContext.currentUserId();
        Boolean bool = redisTemplate.opsForValue().setIfAbsent(key, "1", 20, TimeUnit.SECONDS);
        if (Boolean.FALSE.equals(bool)) {
            throw new CommonException("请勿重复下单");
        }
        //创建责任链对象
        CheckOrderHandler checkOrderHandler = new CheckOrderHandler();
        FillOrderHandler fillOrderHandler = new FillOrderHandler();
        CalculateOrderHandler calculateOrderHandler = new CalculateOrderHandler();
        SavaOrderHandler savaOrderHandler = new SavaOrderHandler();
        AfterOrderHandler afterOrderHandler = new AfterOrderHandler();
        //  责任连流程
        checkOrderHandler.setOrderHandler(fillOrderHandler);
        fillOrderHandler.setOrderHandler(calculateOrderHandler);
        calculateOrderHandler.setOrderHandler(savaOrderHandler);
        savaOrderHandler.setOrderHandler(afterOrderHandler);
        // 启动任务
        Orders orders = new Orders();
        checkOrderHandler.process(orders, placeOrderReqDTO);
        PlaceOrderResDTO placeOrderResDTO = new PlaceOrderResDTO();
        placeOrderResDTO.setId(orders.getId());

        return placeOrderResDTO;
    }

    @Override
    public void cancelOrder(OrderCancelReqDTO orderCancelReqDTO) {
        //修改订单状态
        Orders byId = super.getById(orderCancelReqDTO.getId());
        if (byId == null) {
            throw new CommonException("订单不存在");
        }
        byId.setCancelReason(orderCancelReqDTO.getCancelReason());
        //如果已支付需要退款
        ExecutionResultResDTO executionResultResDTO = new ExecutionResultResDTO();
        if (byId.getPayStatus() == OrderPayStatusEnum.PAY_SUCCESS.getStatus()) {
            if (!Objects.equals(byId.getOrdersStatus(), OrderStatusEnum.DISPATCHING.getStatus())) {
                throw new CommonException("请联系客服");
            }
            try {
                executionResultResDTO = refundRecordApi.refundTrading(byId.getTradingOrderNo(), byId.getRealPayAmount());
                byId.setRefundNo(executionResultResDTO.getRefundNo());
                byId.setRefundId(executionResultResDTO.getRefundId());
                byId.setPayStatus(executionResultResDTO.getRefundStatus());
            } catch (Exception e) {
                throw new CommonException("退款失败");
            }
        } else {
            //未支直接取消订单
            byId.setOrdersStatus(OrderStatusEnum.CANCELED.getStatus());
            super.updateById(byId);
        }
        //新增取消记录
        ordersCanceledService.cancelOrder(orderCancelReqDTO.getId(), orderCancelReqDTO.getCancelReason());
    }

    /**
     * 订单支付
     *
     * @param id              订单id
     * @param ordersPayReqDTO 订单支付参数
     * @return
     */
    @Override
    public OrdersPayResDTO pay(Long id, OrdersPayReqDTO ordersPayReqDTO) {
        PayReqDTO payReqDTO = new PayReqDTO();
        Orders orders = super.getById(id);
        if (orders == null) {
            throw new CommonException("订单不存在");
        }
        //封装支付请求参数
        payReqDTO.setProductOrderNo(orders.getId());
        payReqDTO.setTradingChannel(ordersPayReqDTO.getTradingChannel());
        payReqDTO.setPayType(PayTypeEnum.NATIVE);
        payReqDTO.setTradingAmount(orders.getRealPayAmount());
        payReqDTO.setMemo(orders.getServeItemName());
        PayResDTO payResDTO = null;
        // 调用支付服务
        try {
            payResDTO = tradingApi.toPay(payReqDTO);
        } catch (Exception e) {
            log.error("支付异常", e);
            throw new RuntimeException(e);
        }
        // 封装支付结果
        OrdersPayResDTO ordersPayResDTO = new OrdersPayResDTO();
        ordersPayResDTO.setTradingOrderNo(Long.valueOf(payResDTO.getPayOrderNo()));
        ordersPayResDTO.setQrCode(payResDTO.getQrCode());
        return ordersPayResDTO;
    }


}
